package com.ponhu.ea2.stockcenter.provider.service.biz.stockwarehouse;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.ponhu.ea2.stockcenter.dto.WMSEventInfoDTO;
import com.ponhu.ea2.stockcenter.enums.ExchangeActionTypeEnum;
import com.ponhu.ea2.stockcenter.provider.entity.StockInventoryDocOccupy;
import com.ponhu.ea2.stockcenter.provider.entity.StockWarehouseChange;
import com.ponhu.ea2.stockcenter.provider.support.exception.StockRuntimeException;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.ponhu.ea2.stockcenter.enums.ExchangeActionTypeEnum.TRANSFER_APPLY;
import static com.ponhu.ea2.stockcenter.enums.ExchangeActionTypeEnum.TRANSFER_APPLY_CANCEL;
import static com.ponhu.ea2.stockcenter.enums.ResponseCodeEnum.STOCK_SALES_EXCEPTION_900301;
import static com.ponhu.ea2.stockcenter.provider.support.enums.StockChangeInnerEventEnum.CANCEL_TRANSFER_APPLY_AND_DOC_NO_CANCELED;
import static com.ponhu.ea2.stockcenter.provider.support.enums.StockChangeInnerEventEnum.CANCEL_TRANSFER_APPLY_AND_NO_DOC_NO_AND_YES_TO_NO;

/**
 * 取消调拨申请
 */
@Component
public class TransferApplyCancelHandler extends AbsCoreHandler {

    public TransferApplyCancelHandler() {
        inOccupy = true;
        operateWarehouse = false; // 当前操作仓库是 outWarehouse
        whActionTypeArr = new ExchangeActionTypeEnum[]{TRANSFER_APPLY_CANCEL};
    }

    @Override
    protected void absHandle(WMSEventInfoDTO eventInfoDTO) {

        // 取消调拨申请仓库校验
        applyCanncelCheck();

        // 仓库库存变动数据库操作
        stockWarehouseHandle(eventInfoDTO);

        // 仓库库存变动对销售库存影响
        salesStockHandle(eventInfoDTO);

        // 取消调拨申请操作
        applyCanncelHandle(eventInfoDTO);
    }

    /**
     * 取消调拨申请仓库校验
     */
    private void applyCanncelCheck() {

        // 货品调拨申请记录集合转Map(key：货品编码，vlue：调拨申请库存数)
        Map<String, Integer> updateNumMap = whChangesLocal.get().stream()
                .filter(change -> TRANSFER_APPLY.getCode().equals(change.getActionType()))
                .collect(Collectors.toMap(StockWarehouseChange::getInventoryCode,
                        StockWarehouseChange::getUpdatedNumAbs));

        // 货品调拨申请数量 == 货品取消申请数量 && 货品锁定库存数 >= 货品取消申请数量
        StringBuffer msg = new StringBuffer();
        absUtilHandler.whStockAllMacth(stock -> {
            Integer updateNum = updateNumMap.get(stock.getInventoryCode());
            Integer inventoryQuantity = inventoryLocal.get().get(stock.getInventoryCode());
            boolean macth = updateNum == inventoryQuantity && stock.getLockedStockNum() >= inventoryQuantity;
            if (BooleanUtils.isNotTrue(macth))
                msg.append(String.format(" 货品编码-%s:{调拨申请库存数(%s) == 调拨请求库存数(%s) && " +
                                "调拨占用库存数(%s) >= 调拨请求库存数(%s)}校验失败；", stock.getInventoryCode(),
                        updateNum, inventoryQuantity, stock.getLockedStockNum(), inventoryQuantity));
            return macth;
        }, msg);
    }

    /**
     * 取消调拨申请操作
     */
    private void applyCanncelHandle(WMSEventInfoDTO eventInfoDTO) {

        // 校验当前调拨申请是否关联业务单据
        if (StringUtils.isEmpty(eventInfoDTO.getDocNo())) return;

        // 校验当前业务单据的有销售侧库存占用
        List<StockInventoryDocOccupy> docRecordList = stockInventoryDocOccupyService
                .getDocRecordList(eventInfoDTO.getDocNo());
        if (CollectionUtils.isEmpty(docRecordList)) return;

        // 有订单占用且订单未取消
        if (saleEventLocal.get() == CANCEL_TRANSFER_APPLY_AND_DOC_NO_CANCELED) {
            if (!stockInventoryDocOccupyService.changeDocRecordToNoTransferAndNoOutAndUsed(
                    eventInfoDTO.getDocNo(), eventInfoDTO.getActionType(), saleEventLocal.get())) {
                throw new StockRuntimeException(STOCK_SALES_EXCEPTION_900301);
            }
        }

        // 有订单占用且订单已取消
        if (saleEventLocal.get() == CANCEL_TRANSFER_APPLY_AND_NO_DOC_NO_AND_YES_TO_NO) {
            if (!stockInventoryDocOccupyService.changeDocRecordToNoTransferAndNoOut(
                    eventInfoDTO.getDocNo(), eventInfoDTO.getActionType(), saleEventLocal.get())) {
                throw new StockRuntimeException(STOCK_SALES_EXCEPTION_900301);
            }
        }
    }

}
